{
 "cells": [
  {
   "attachments": {},
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Playbook to showcase KubeHound against our demo kind cluster\n",
    "\n",
    "This notebook (and the ones next to it in this folder) will be in sync between the docker container and the hosts.\n",
    "You can use this to experiment and save your queries in git, if needed.\n",
    "This file is persistant.\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Initial Setup\n",
    "\n",
    "Connection is being initated directly from the docker using the env vars `GRAPH_NOTEBOOK_HOST` and `GRAPH_NOTEBOOK_PORT`. To overwrite it you can use the magic `%%graph_notebook_config` [details here](https://github.com/aws/graph-notebook/tree/main/additional-databases/gremlin-server#connecting-to-a-local-gremlin-server-from-jupyter).\n",
    "\n",
    "Now set the appearance customizations for the notebook. You can see a guide on possible options [here](https://github.com/aws/graph-notebook/blob/623d43827f798c33125219e8f45ad1b6e5b29513/src/graph_notebook/notebooks/01-Neptune-Database/02-Visualization/Grouping-and-Appearance-Customization-Gremlin.ipynb#L680)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "init_cell": true
   },
   "outputs": [],
   "source": [
    "%%capture \"Remove this line to see debug information\"\n",
    "%%graph_notebook_vis_options\n",
    "{\n",
    "  \"edges\": {\n",
    "    \"smooth\": {\n",
    "      \"enabled\": true,\n",
    "      \"type\": \"dynamic\"\n",
    "    },\n",
    "    \"arrows\": {\n",
    "      \"to\": {\n",
    "        \"enabled\": true,\n",
    "        \"type\": \"arrow\"\n",
    "      }\n",
    "    }\n",
    "  }\n",
    "}"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### What are we looking at ?\n",
    "\n",
    "Let's see the big pictures of our cluster."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d label -g class -le 50 -p inv,oute\n",
    "kh.V().path().by(elementMap())"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d label -g class -le 50 -p inv,oute\n",
    "kh.V().criticalPaths().by(elementMap()).limit(2000)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Well, this is bad. This cluster is definitely not secured. We need to focus on what make actually sense from a real attacker perspective. \n",
    "\n",
    "### Let's look at the containers then"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d label -g class -le 50 -p inv,oute\n",
    "kh.containers().criticalPaths().by(elementMap())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Nop, still too much result, let's try to narrow it down. What is more important than the containers ? Endpoint, because they are the component that actually exposed service.\n",
    "Supply chain attack are great but they are sophisticated. \n",
    "\n",
    "### Let's look at the basic, the endpoints"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d name -g class -le 50 -p inv,oute\n",
    "kh.endpoints().criticalPaths().by(elementMap())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "OK this is making more sense, let's get the context of the associated endpoint that leads to a critical attack path.\n",
    "\n",
    "### Let's get the vulnerability context"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d name -g class -le 50 -p inv,oute\n",
    "kh.endpoints().criticalPaths().limit(local,1)\n",
    ".dedup().valueMap(\"serviceEndpoint\",\"port\")\n",
    ".group().by(\"serviceEndpoint\").by(\"port\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "OK so all are not equal, and some are not in our interest. Let's remove the `kube-dns` service.\n",
    "\n",
    "### Let's look at the specific services that interest us"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d label -g class -le 50 -p inv,oute\n",
    "kh.endpoints().not(has(\"serviceEndpoint\",\"kube-dns\")).criticalPaths().by(elementMap())"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Ok, so once we land on the node, it is game over. This will require too much in-depth security. So let's focus on the first initial stage first.\n",
    "\n",
    "### Initial exposure identified"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "%%gremlin -d label -g class -le 50 -p inv,oute\n",
    "kh.endpoints().not(has(\"serviceEndpoint\",\"kube-dns\"))\n",
    "\t.repeat(\n",
    "\t\toutE().inV().simplePath()\n",
    "\t)\n",
    "\t.until(\n",
    "\t\thasLabel(\"Node\")\n",
    "\t\t.or()\n",
    "\t\t.loops().is(5)\n",
    "\t)\n",
    "\t.hasLabel(\"Node\")\n",
    "\t.path()\n",
    "\t.by(elementMap())\n",
    "\t.limit(100)\t// Limit the number of results for large clusters"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here we have, the \"true\" findings that need our attention."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.16"
  },
  "orig_nbformat": 4
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
